package jp.sourceforge.akjrcp.util.image;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;

import jp.sourceforge.akjrcp.psp.imageconvert.ImageTurner;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.plugin.AbstractUIPlugin;

public class ImageUtils {

	public static Image createThumbnail(Image img,int width,int height){
		
		Image retImage=new Image(null,width,height);
		GC gc=new GC(retImage);
		gc.setBackground(new Color(null,255,255,255));
		gc.fillRectangle(0,0,retImage.getBounds().width,retImage.getBounds().height);
		
		if(img.getBounds().width>retImage.getBounds().width || img.getBounds().height>retImage.getBounds().height){
			int overw=img.getBounds().width-retImage.getBounds().width;
			int overh=img.getBounds().height-retImage.getBounds().height;
			double ratio=0;
			if(overw>overh){
				ratio=(double)retImage.getBounds().width/img.getBounds().width;
			}else{
				ratio=(double)retImage.getBounds().height/img.getBounds().height;
			}
			int dw=(int)(img.getBounds().width*ratio);
			int dh=(int)(img.getBounds().height*ratio);
			int cx=(retImage.getBounds().width-dw)/2;
			int cy=(retImage.getBounds().height-dh)/2;
			gc.drawImage(img,0,0,img.getBounds().width,img.getBounds().height,cx,cy,dw,dh);
			
		}else{
			int cx=(retImage.getBounds().width-img.getBounds().width)/2;
			int cy=(retImage.getBounds().height-img.getBounds().height)/2;
			gc.drawImage(img,0,0,img.getBounds().width,img.getBounds().height,cx,cy,img.getBounds().width,img.getBounds().height);
		}
		gc.dispose();
		return retImage;
	}

	public static BufferedImage toRGB(BufferedImage img) {
		BufferedImage ret=new BufferedImage(img.getWidth(),img.getHeight(),BufferedImage.TYPE_INT_RGB);
			ret.getGraphics().drawImage(img,0,0,null);
			
		return ret;
	}
	public static void writeJpegWithQuality(BufferedImage image, File file,float quality) throws IOException {
		 ImageWriter imageWriter = null;
		    Iterator imageWriterIterator =
		      ImageIO.getImageWritersByFormatName("jpeg");
		    if(imageWriterIterator.hasNext()) {
		      imageWriter = (ImageWriter)imageWriterIterator.next();
		    }
		    if(imageWriter == null) {
		      throw new IOException("imageWriter not found");
		    }
		   
		    ImageOutputStream imageOutputStream =
		      ImageIO.createImageOutputStream(file);
		    imageWriter.setOutput(imageOutputStream);
		    IIOImage iioImage = new IIOImage(image, null, null);
		    ImageWriteParam imageWriteParam =
		      new JPEGImageWriteParam(null);
		    imageWriteParam.setCompressionMode(
		      ImageWriteParam.MODE_EXPLICIT);
		    imageWriteParam.setCompressionQuality(quality);
		    imageWriter.write(null, iioImage, imageWriteParam);
		    imageOutputStream.close();
		    imageWriter.dispose();
	}

	public static void writeJpegWithQuality(BufferedImage image,OutputStream output,float quality) throws IOException {
		 ImageWriter imageWriter = null;
		    Iterator imageWriterIterator =
		      ImageIO.getImageWritersByFormatName("jpeg");
		    if(imageWriterIterator.hasNext()) {
		      imageWriter = (ImageWriter)imageWriterIterator.next();
		    }
		    if(imageWriter == null) {
		      throw new IOException("imageWriter not found");
		    }
		   
		    ImageOutputStream imageOutputStream =
		      ImageIO.createImageOutputStream(output);
		    imageWriter.setOutput(imageOutputStream);
		    IIOImage iioImage = new IIOImage(image, null, null);
		    ImageWriteParam imageWriteParam =
		      new JPEGImageWriteParam(null);
		    imageWriteParam.setCompressionMode(
		      ImageWriteParam.MODE_EXPLICIT);
		    imageWriteParam.setCompressionQuality(quality);
		    imageWriter.write(null, iioImage, imageWriteParam);
		    
		    imageOutputStream.flush();
		    //imageOutputStream.close();
		    //imageWriter.dispose();
		    //if(FFMpegFLVFileEffector.count>817){
		    	//log.infodone write jpeg:"+FFMpegFLVFileEffector.count);
		    //}
	}
	
	/**
	 * 
	 * @param image
	 * @param size
	 * @return image expanded size*2
	 */
	public static BufferedImage getBluredImage(BufferedImage image,int size){
		float[] elements = new float[size*size];
		float v=1.0f/elements.length;
		for (int i = 0; i < elements.length; i++) {
			elements[i]=v;
		}
		BufferedImage base=new BufferedImage(image.getWidth()+size*2,image.getHeight()+size*2,BufferedImage.TYPE_INT_RGB);
		base.getGraphics().drawImage(image,size,size,null);
		//copy w
		base.getGraphics().copyArea(size, size, size, image.getHeight(), -size, 0);
		base.getGraphics().copyArea(image.getWidth()+size-size, size, size, image.getHeight(), size, 0);
		//copy h
		base.getGraphics().copyArea(0, size, image.getWidth()+size*2, size, 0, -size);
		base.getGraphics().copyArea(0, image.getHeight()+size-size, image.getWidth()+size*2, size, 0, size);
		
		BufferedImage bimg = new BufferedImage(image.getWidth()+size*2,image.getHeight()+size*2,BufferedImage.TYPE_INT_RGB);
		 Kernel kernel = new Kernel(size, size, elements);
	       ConvolveOp cop = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); //ConvolveOp.EDGE_ZERO_FILL is just black
		cop.filter(base,bimg);
		
		return bimg;
		
	}

	/*
	 * "jp/sourceforge/akjrcp/psp/resource/noimage.png")
	 */
	public static Image loadImage(Class cl,String resource){
	Image ret = new Image(Display.getCurrent(),
			cl.getClassLoader().getResourceAsStream(
					resource));
	return ret;
	}

	public static Image loadImage(String pluginID,String name){
	
	return AbstractUIPlugin.imageDescriptorFromPlugin(
			pluginID, name).createImage();
	}
	
	private static String[] imageExtensions={"png","jpg","jpeg","gif"};
	public static boolean isImageFile(String path){
		if(path==null){
			return false;
		}
		for (int i = 0; i < imageExtensions.length; i++) {
			if(path.toLowerCase().endsWith("."+imageExtensions[i])){
				return true;
			}
		}
		return false;
	}
	public static boolean isJpegFile(String path){
		return path.toLowerCase().endsWith("."+"jpg") ||path.toLowerCase().endsWith("."+"jpeg");
	}
	
	public static boolean isPngFile(String path){
		return path.toLowerCase().endsWith("."+"gif");
	}
	
	public static boolean isGifFile(String path){
		return path.toLowerCase().endsWith("."+"png");
	}

	public static BufferedImage resizeImage(BufferedImage baseImage,int width,int height){
		
		ImageTurner.log.trace("baseW="+baseImage.getWidth()+" baseH="+baseImage.getHeight());
		int dw=width;
		int dh=height;
		
		
		if(dw!=0 && dh!=0 ){
			double waspect=(double)dw/baseImage.getWidth();
			double haspect=(double)dh/baseImage.getHeight();
			if(waspect>haspect){//fit h
				dw=(int) (baseImage.getWidth()*haspect);
				
			}else{
				dh=(int)(baseImage.getHeight()*waspect);
			}
			ImageTurner.log.trace("waspect="+waspect+" haspect="+haspect+" dw="+dw+" dh="+dh);
		}
		BufferedImage image = new BufferedImage(dw, dh, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g2=(Graphics2D) image.getGraphics();
		g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		int dx=0;
		int dy=0;
		ImageTurner.log.trace("dx="+dx+",dy="+dy);
		g2.drawImage(baseImage, dx, dy, dw+dx, dh+dy,0, 0, baseImage.getWidth(), baseImage.getHeight(),  null);
		return image;
	}
	
	public static BufferedImage fitImage(BufferedImage baseImage,int width,int height){
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		ImageTurner.log.trace("baseW="+baseImage.getWidth()+" baseH="+baseImage.getHeight());
		int dw=width;
		int dh=height;
		
		
		if(dw!=0 && dh!=0 ){
			double waspect=(double)dw/baseImage.getWidth();
			double haspect=(double)dh/baseImage.getHeight();
			if(waspect>haspect){//fit h
				dw=(int) (baseImage.getWidth()*haspect);
				
			}else{
				dh=(int)(baseImage.getHeight()*waspect);
			}
			ImageTurner.log.trace("waspect="+waspect+" haspect="+haspect+" dw="+dw+" dh="+dh);
		}
		
		Graphics2D g2=(Graphics2D) image.getGraphics();
		g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		int dx=(width-dw)/2;
		int dy=(height-dh)/2;
		ImageTurner.log.trace("dx="+dx+",dy="+dy);
		g2.drawImage(baseImage, dx, dy, dw+dx, dh+dy,0, 0, baseImage.getWidth(), baseImage.getHeight(),  null);
		return image;
	}
	/*
	 * TODO keep alpha
	 */
	public  static BufferedImage clipImage(BufferedImage baseImage,int x,int y,int width,int height,java.awt.Color bgColor) throws IOException{
		BufferedImage clipImage=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
		Graphics g=clipImage.getGraphics();
		if(bgColor!=null){
			g.setColor(bgColor);
			g.fillRect(0, 0, width, height);
			}
		g.drawImage(baseImage, -x,-y,null);
		return clipImage;
	}

}
